import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { Card, message, Table, Button, Form, Input, Select, Row, Col, Radio, Tabs  } from 'antd';
import { FormInstance } from 'antd/lib/form';
import styles from '@/components/common/PateoTable/TableList.less';
import style from './index.less';
import classnames from 'classnames';
import { wrap } from 'lodash';
import TreeView from '../knowledge/treeView'
import { Graph, Model, Node, Edge, Shape } from '@antv/x6'
import Hierarchy from '@antv/hierarchy';
import CaseViewModal from './caseViewModal'

interface HierarchyResult {
  id: any
  x: number
  y: number
  data: {
    faultCode: string
    faultDescription: string
    isSearch: boolean
  }
  children: HierarchyResult[]
}
const FormItem = Form.Item;
const mapStateToProps = (state: any) => ({
  breakdownSearch: state.breakdownSearch,
  loading: state.loading.models['breakdownSearch'],
});
class BreakdownSearch extends PureComponent<any, any> {
  formRef = React.createRef<FormInstance>();
  constructor(props: any) {
    super(props);
    this.state = {
      currentType: 'page1',
      currentMajorCode: '',
      screenFit: '1',
      top6Data: [],
      tabsData: [],
      // secondaryNodes: [], //  二级节点数据
      secondaryNodesIds: [],  //  二级节点id
      secondaryNodesTree: {}, //  二级节点树数据（list）
      currentData: [],  //  当前申请故障数据
      currentIds: {}, //  当前申请故障数据关系
      currentTargetModel: [],
      caseVisible: false,
      caseRecord: {},
    }
  }

  componentDidMount() {
    const { dispatch } = this.props;
    dispatch({
      type: 'http/getDataWithRes',
      payload: { 
        url: '/mscontent/knowledge/fault/findFault',
        orderBy: 'caseNum',
        limitNum: 6,
      },
      callback: (res: any) => {
        if (res.statusCode == '0') {
          this.setState({
            top6Data: res.data || [],
          })
        }
      }
    })
  }

  //  故障检索
  queryFault = (word: any) => {
    const { dispatch } = this.props;
    dispatch({
      type: 'http/getDataWithRes',
      payload: { 
        url: '/mscontent/knowledge/fault/searchFault',
        word: word,
      },
      callback: (res: any) => {
        if (res.statusCode == '0') {
          const tempResult = this.formatResultData(res.data || []);
          const { secondaryNodes, secondaryNodesIds, secondaryNodesTree } = tempResult;
          this.setState({
            currentType: 'page2',
            tabsData: secondaryNodes,
            secondaryNodesIds: secondaryNodesIds,
            secondaryNodesTree: secondaryNodesTree
          })
          if (secondaryNodes.length > 0) {
            this.setState({
              currentMajorCode: secondaryNodes[0].id
            })
            this.getTreeData(secondaryNodes[0].id)
          }
        }
      }
    })
  }

  //  处理搜索结果数据
  formatResultData = (list: any[]) => {
    let secondaryNodes: any[] = [];  //  二级节点
    let secondaryNodesIds: any[] = [];
    let secondaryNodesTree = {};  
    list.forEach((item: any) => {
      if (item.id == item.secondaryRootId) {
        //  二级节点
        secondaryNodesIds.push(item.id);
        secondaryNodes.push({
          ...item
        })
      }
    })
    list.forEach((item: any) => {
      if (secondaryNodesIds.indexOf(item.secondaryRootId) !== -1) {
        if (secondaryNodesTree[item.secondaryRootId]) {
          secondaryNodesTree[item.secondaryRootId].push({
            ...item,
          })
        } else {
          secondaryNodesTree[item.secondaryRootId] = [
            {
              ...item,
            }
          ]
        }   
      }
    })
    return {
      secondaryNodes,
      secondaryNodesIds,
      secondaryNodesTree,
    }
  }


  handleQuery = (item: any) => {
    this.formRef?.current?.setFieldsValue({
      word: item.faultDescription
    })
    
    this.queryFault(item.faultDescription);
  }
 
  //  提交数据
  ok = (values: any) => {
    const { word } = values
    if ( !word ) {
      message.warning('请输入搜索信息');  
      return;
    }
    this.formRef?.current?.setFieldsValue({
      word: word.trim()
    })
    this.treeViewRef.clearGraph();
    this.queryFault(word);
  }

  getTreeData = (id: any) => {
    const { secondaryNodesTree } = this.state;
    const treeList = JSON.parse(JSON.stringify(secondaryNodesTree[id]));
    const sourceData = this.formatSourceTreeData(treeList);
    const sourceDataList = this.treeToArray(sourceData, '');
    const fullData = this.formatTreeData(sourceDataList);
    const fullDataIds = this.getFulltreeIds(fullData);
    //  计算坐标
    const fullDataModel = this.getCoordinates(fullData[0]);

    const fullTargetModel = this.transformModel(fullDataModel, fullDataIds);
    this.setState({
      currentMajorCode: id,
    })
    if (fullTargetModel.nodes && fullTargetModel.nodes.length > 0) {
      this.treeViewRef.setData(fullTargetModel, fullDataIds);
    } else {
      this.treeViewRef.clearGraph();
    }
  }

  //  处理接口返回完整知识库 list 数据
  formatSourceTreeData = (list: []) => {
    return this.arrayToTree(list, 'parentId');
  }

  arrayToTree = (items: any, pKey: string) => {
    let res = []; // 存放结果集
    let map = {};
    // 判断对象是否有某个属性
    let getHasOwnProperty = (obj: any, property: any) => Object.prototype.hasOwnProperty.call(obj, property);
    // 边做map存储，边找对应关系
    for (const i of items) {
      map[i.id] = {
        ...i,
        // title: i.faultCode + '-' + i.faultDescription,
        children: getHasOwnProperty(map, i.id)
          ? map[i.id].children
          : [],
      };
      const newItem = map[i.id];
      if (i.secondaryRootId == i.id) {
        //  二级节点作为根节点，无父级
        res.push(newItem);
      } else {
        if (!getHasOwnProperty(map, i[pKey])) {
          map[i[pKey]] = {
            children: [],
          };
        }
        map[i[pKey]].children.push(newItem);
      }
    }
    return res;
  }

  //  添加 parrentCode（使用 faultCode 构建关系）
  treeToArray = (tree: any, pcode: string) => {
    let res: any[] = [];
    for (const item of tree) {
      const {
        children,
        faultCode,
        faultDescription,
        ...i
      } = item;
      if (children && children.length > 0) {
        const temp = this.treeToArray(children, faultCode);
        res = res.concat(temp);
      }
      res.push({
        faultCode,
        faultDescription,
        parrentCode: pcode,
        ...i
      });
    }
    return res;
  }

  //  整理树数据（处理重复 faultCode 数据）
  formatTreeData = (sourceData: any[]) => {
    const tempSource = JSON.parse(JSON.stringify(sourceData));
    let tempFullData: any[] = [];
    let res = {};
    tempSource.forEach((item: any) => {
      res[item.faultCode] = {
        ...item,
      };
    });
    tempFullData = this.arrayToTree1(Object.values(res));
    return tempFullData;
  }

  //  array -> tree
  arrayToTree1 = (items: any) => {
    let res = []; // 存放结果集
    let map = {};
    // 判断对象是否有某个属性
    let getHasOwnProperty = (obj: any, property: any) => Object.prototype.hasOwnProperty.call(obj, property);
    // 边做map存储，边找对应关系
    for (const i of items) {
      map[i.faultCode] = {
        ...i,
        children: getHasOwnProperty(map, i.faultCode)
          ? map[i.faultCode].children
          : [],
      };
      const newItem = map[i.faultCode];
      if (i.parrentCode === "") {
        res.push(newItem);
      } else {
        if (!getHasOwnProperty(map, i.parrentCode)) {
          map[i.parrentCode] = {
            children: [],
          };
        }
        map[i.parrentCode].children.push(newItem);
      }
    }
    return res;
  }

  //  获取完整树节点关系
  getFulltreeIds = (data: any[]) => {
    const ids = {};
    function formatData(tree: any[]) {
      for (let item of tree) {
        const { children } = item
        ids[item.id] = [];  //  faultCode、id
        if (children.length > 0) {
          ids[item.id] = children.map(t => t.id);
          formatData(children)
        }
      }
    }
    if (data[0]) {
      const topicChildren = data[0]?.children || [];
      ids[data[0].id] = topicChildren.map(t => t.id);
      topicChildren && formatData(data[0]?.children);
    }
    return ids;
  }

  //  计算坐标
  getCoordinates = (data: any) => {
    if (data) {
      const result = Hierarchy.mindmap(data, {
        direction: 'H',
        getHeight() {
          return 120
        },
        getWidth() {
          return 100
        },
        getHGap() {
          return 200
        },
        getVGap() {
          return 1
        },
        getSide: () => {
          return 'right'
        },
      })
      const model: Model.FromJSONData = { nodes: [], edges: [] };
      const traverse = (data: HierarchyResult) => {
        // console.log(data);
        let tempCaseNum = data.data.caseNum ?? 0;
        if (data) {
          model.nodes?.push({
            id: `${data.id}`, //  使用id
            x: data.x + 250,
            y: data.y + 250,
            code: data.data.faultCode,
            desp: data.data.faultDescription,
            isSearch: data.data.isSearch,
            caseNum: tempCaseNum,
            // title: data.data.faultDescription,
            shape: 'circle',
            width: 260,
            height: 88,
            attrs: {
              body: {
                fill: '#5F95FF',
                stroke: 'transparent',
                rx: 10,
                ry: 10,
              },
            },
          })
        }
        if (data.children) {
          data.children.forEach((item: HierarchyResult) => {
            model.edges?.push({
              source: `${data.id}`, //  data.id data.data.faultCode
              target: `${item.id}`, //  item.id item.data.faultCode
              attrs: {
                line: {
                  stroke: '#A2B1C3',
                  strokeWidth: 1,
                  targetMarker: null,
                },
              },
            })
            traverse(item)
          })
        }
      }
      traverse(result);
      return model;
    } else {
      return {
        nodes: [],
        edges: [],
      }
    }
  }

  //  转换数据
  transformModel = (model: any, ids: any) => {
    let data = JSON.parse(JSON.stringify(model));
    const { nodes, edges } = data
    let targetModel: any = { nodes: [], edges: edges };
    nodes.forEach((n: any, idx: number) => {
      //  使用的二级节点作为根节点，有故障编码
      let tempInfo = {
        code: n.code,
        text: n.desp
      };
      /* let tempInfo = {
        code: '',
        text: n.desp
      };
      if (idx !== 0) {
        //  起始
        tempInfo.code = n.code;
      } */
      let tempN = {
        id: n.id,
        shape: 'tree-node',
        width: 260,
        height: 88,
        leaf: !(ids[n.id] && ids[n.id].length > 0),
        leafLen: ids[n.id] ? ids[n.id].length : 0,
        isSearch: n.isSearch,
        caseNum: n.caseNum,
        x: n.x,
        y: n.y,
        attrs: {
          code: {
            textWrap: {
              text: tempInfo.code
            }
          },
          label: {
            textWrap: {
              text: tempInfo.text
            }
          },
          case: {
            textWrap: {
              text: `案例数: ${n.caseNum}`
            }
          }
        }
      }
      targetModel.nodes.push(tempN);
    })
    return targetModel;
  }

  //  查看案例文档
  viewCaseModal = (n: any) => {
    const { tabsData, currentMajorCode, secondaryNodesTree } = this.state;
    let tempRecord = {};
    const list = secondaryNodesTree[currentMajorCode] || [];
    list.some((t: any) => {
      const status = n.id == t.id;
      if (status) {
        tempRecord = {
          ...t
        }
      }
      return status;
    })
    this.setState({
      caseVisible: true,
      caseRecord: tempRecord
    })
  }

  //  关闭案例文档
  closeCaseModal = () => {
    this.setState({
      caseVisible: false,
      caseRecord: {}
    })
  }

  //  画笔比列
  handleGraphFit = (val: any) => {
    this.setState({
      screenFit: val,
    })
    if (this.treeViewRef) {
      const { graph } = this.treeViewRef.state;
      if (val === '1' ) {
        //  适应画布
        graph && graph.zoomToFit({ padding: 24 });
      } else if (val === '2') {
        //  100%
        graph && graph.zoomTo(1);
      }
    }
  }

  render() {
    const { currentType, top6Data, tabsData, caseVisible, caseRecord, screenFit } = this.state;
    const submitBtn = (
      <Form.Item noStyle>
        <Button onClick={() => {
          this.formRef?.current?.submit();
        }}>故障查询</Button>
      </Form.Item>
    );

    return (
      <div>
        <Card 
          className={classnames(styles.standardTable, {
            [style.page1]: currentType === 'page1',
            [style.page2]: currentType === 'page2',
          })} 
          style={{ 
            height: 'calc(100vh - 116px)',
            minHeight: currentType === 'page1' ? '300px' : '1100px'
          }}
        >
          <Form
            className={style.searchForm}
            ref={this.formRef}
            onFinish={this.ok}
          >
            <Form.Item
              name="word"
              label=" "
              style={{ width: '100%' }}
              colon={false}
              rules={[]}
            >
              <Input addonAfter={submitBtn} style={{ width: '100%' }} />
            </Form.Item>
          </Form>
          <div className={style.top6}>
            {top6Data && top6Data.length > 0 ? (
              <>
                {top6Data.map((item: any, idx: number) => (
                  <div className={style.topItem} key={item.id}>
                    <div className={style.box} onClick={() => {
                      this.handleQuery(item);
                    }}>
                      <div className={style.num}>{idx + 1}</div>
                      <div className={style.msg}>{item.faultDescription}</div>
                    </div>
                  </div>
                ))}
              </>
            ) : null }
          </div>
          <div className={style.tabs}>
            <Tabs 
              // defaultActiveKey="1" 
              type="card"
              onChange={(key) => {
                this.getTreeData(key);
              }}
            >
              <>
                {tabsData.map((item: any, idx: number) => {
                  const title = item.faultType;
                  return <Tabs.TabPane tab={title} key={item.id}></Tabs.TabPane>
                })}
              </>
            </Tabs>
            <div style={{ position: 'relative', width: '100%', border: '1px solid #ccc' }}>
              <TreeView
                onRef={(modalRef: any) => (this.treeViewRef = modalRef)}
                clickNode={(n: any) => {
                  // faultCode
                  this.viewCaseModal(n);
                }}
                styels={{
                  width: '100%',
                  height: '900px'
                }}
              />
              <div style={{ position: 'absolute', right: '65px', bottom: '80px', }}>
                {/* 适应画布、100% */}
                <Select
                  style={{
                    width: '100px',
                  }}
                  value={screenFit}
                  placeholder="缩放比列"
                  onSelect={(v: any) => {
                    this.handleGraphFit(v);
                  }}
                  options={[
                    {
                      value: '1',
                      label: '适应画布',
                    },
                    {
                      value: '2',
                      label: '100%',
                    },
                  ]}
                />
              </div>
            </div>
          </div>
        </Card>
        <CaseViewModal
          onRef={(modalRef: any) => (this.caseViewModal = modalRef)}
          modalVisible={caseVisible}
          record={caseRecord}
          // pathname={pathname}
          closeModal={this.closeCaseModal}
        />
      </div>
    )
  }
}
export default connect(mapStateToProps)(BreakdownSearch);
